package interfaces.general.cuadrantes;

import interfaces.general.ObservadorCargaCache;

import java.sql.Time;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.ResourceBundle;

import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DateTime;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.ScrollBar;

import algoritmo.Sugerencia;
import algoritmo.Trabaja;
import algoritmo.Cuadrante;
import aplicacion.Vista;
import aplicacion.datos.Empleado;
import aplicacion.datos.Turno;
import aplicacion.utilidades.Dibujable;
import aplicacion.utilidades.Posicion;
import aplicacion.utilidades.Util;

/**
 * Esta clase extiende la clase Cuadrante para que se pueda:<br>
 * 1. dibujar sobre un GC<br>
 * 2. representar y modificar sobre un canvas<br>
 * @author Daniel Dionne y Miguel Ángel Alonso
 */
public class I_Cuadrante extends algoritmo.Cuadrante implements Dibujable, ObservadorCargaCache{
//Declaración de constantes
//private int ALTO_FRANJAS_SHELL = 15;
//private int SEP_VERT_FRANJAS_SHELL = 10;
	
	private Display display;				// Puntero al display				
	private int anchoImagen, altoImagen;	// Tamaño del cuadrante
	private int margenIzq, margenDer, margenSup, margenInf; // Márgenes del cuadrante
	private int margenNombres;				// Margen para pintar los nombres a la izquierda
	private int alto_franjas = 15;			// Alto de las franjas
	private int sep_vert_franjas = 10;		// Separación vertical entre franjas
	private int horaApertura, horaCierre;	// Definen de qué hora a qué hora es el cuadrante
	private int sep;						// Ancho horizontal de las horas
	private int tamHora, tamSubdiv;
	private int numSubdivisiones;			// Cuántas subdivisiones hacer por hora (0 = sin subdivisiones)
	private Vista vista;					// Puntero a la Vista de la aplicación
	private Canvas canvas;					// Canvas sobre el que se pintan los cuadrantes
	private I_Turno turno = null;			// Esta dovariabldoe sirve dopara cuanddoo se esté configurando un dosolo turno.
	private int despMouse;					// El desplazamiento vertical del ratón al mover empleados
//private int trasteando = 0;
	private boolean enabled; 				// Dice si el widget está activado
	/** 1 vista mensual, 2 vista diaria. */
	private int tipoVista=2;
	/** 1 vista mensual, 2 vista diaria. */
	private int tipoImpresion=0;
	
	// La variable terminadoDeCrear sirve para que una franja nueva no desaparezca al crearla
	/** El empleado sobre el que está el cursor */
	private int empleadoActivo = -1;
	private I_Turno turnoActivo  = null;	// Este turno es para el interfaz de creación de turnos
	private boolean moviendoEmpleado = false;	// Indica si estamos desplazando al empleado
	private Label lGridCuadrante;	//Variables para el combo de las subdivisiones de la vista diaria
	private Combo cGridCuadrante;
	private Label lCuadranteTitulo;	//Etiqueta que indica la fecha en ambas vistas
	
	private int dia=1;	//Atributos del cuadrante
	private int mes=1;
	private int anio=1970;
	private String departamento;
	private Image fondo;
	
	private int diaActVistaMes = 0;		// El día activo en la vista mensual
	private int empActVistaMes = 0;		// El empleado activo en la vista mensual
	private int indiceEmpAct = 0;		// Índice del empleado activo en el ArrayList icuad[dia]
	private boolean diaValido=false;	// Flags para indicar eventos
	private boolean nombreValido=false; 
	private String nombreSeleccionado=null; //Nombre pulsado en la pantalla
	private int nombreMarcado=0;
	private boolean enCuadricula=false; //Más flags para eventos
//private boolean enCuadro=false;
	private int turnPulsX=0;
	private int turnPulsY=0;
	
	private Button bPorMes, bPorDia, bGuardar, bDeshacer, bRehacer;	// Botones del shell
	
	private Turno turnoSeleccionado = null; //Variables para almacenar objetos seleccionados
											//mediante eventos 
	private Empleado empleadoSeleccionado = null;
	private Empleado empleadoSeleccionadoSec = null;
	private I_Trabaja casillaSeleccionada = null;
	
	private int altoFila=0; //Variables para pintar la cuadricula
	private int anchoDia=0;
	private int origen=0; // El origen del dibujo (para desplazarlo verticalmente)
	private int margenSupVistaMes;
	
	private int meses31[]=new int[7]; //Arrays con la información de los meses, para el cálculo
										//de los domingos en la cuadricula
	private int meses30[]=new int[4];
	
	private Color azulOsc = new Color(display,0,110,200); //Algunos colores usados
	private Color azulClar= new Color(display,0,30,120);
	private Color blanco = new Color(display,255,255,255);
	private Color negro = new Color(display,0,0,0);
	
	private Point cursor = new Point(0,0); //Cursor
	
	private int movimiento; //Más flags
	private ScrollBar vBar;
	private boolean moviendoPestanas = false;
	
	private MouseListener mouseListenerCuadrDiario; //Capturadores de eventos del ratón
	private MouseMoveListener mouseMoveListenerCuadrDiario;
	private MouseListener mouseListenerCuadrMensual;
	private MouseMoveListener mouseMoveListenerCuadrMensual;
	private PaintListener paintListener;
	
	private ArrayList<Empleado> empleadosMostrados;	//Array de empleados mostrados en la vista día
	
	private boolean menuContAbierto = false; //Flag para el menú contextual
	
	private boolean cuadModificado = false; //Flag para detectar modificaciones en el cuadrante
	private Cuadrante cuadInicialDeshacer = null; //Variable que almacenará el cuadrante inicial
													//mostrado en la aplicación
	private boolean primerCuad = true;	//Más flags
	private boolean primerCuadActivo = false;
	private boolean pilaRebosada = false;
	private int maxLongNombre = 0; //Para obtener la longitud máxima de los nombres mostrados en la
									//vista mensual
	/**Historial de las modificaciones en los cuadrantes*/
	private CaretakerCuadrante historialPilas = new CaretakerCuadrante();
	
	/* Estas dos variables controlan si los datos cargados de caché están actualizados */
	private boolean cacheCargada = false;
	private java.util.Date timeLastUpdate = new java.util.Date(0);
	
	/**
	 * Paquete de idiomas de la aplicación.
	 */
	private final ResourceBundle bundle;
	
	/**
	 * Hilo que carga el cuadrante al iniciar la aplicación
	 * @author Daniel Dionne
	 */
	public class Loader extends Thread {
		public void run() {
			setName("Cuadrante Loader");
			if (turno==null) {
				try {
					/* Esperar a que la caché principal esté cargada */
					while(!actualizar()) {
						sleep(50);
					}
					actualizarDesdeCache();					// Copiar los datos localmente
					//llenaCuadInicial();
					redibujar();							// Redibujar con los datos nuevos
				}
				catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * Hilo que se encarga del movimiento automático (animación) de las pestañas
	 * @author Daniel Dionne
	 */
	private class Animator extends Thread {
		public void run() {
			try {
				while (vista.isAlive()) {
					if (moviendoPestanas) redibujar();		// Actualizar movimiento de las pestañas
					sleep(20);
				}
			}
			catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * Clase que representa el turno que tiene un empleado un día concreto.
	 * @author Daniel Dionne
	 */
	public class I_Trabaja {
		private Empleado empl;	//id del empleado
		private Time FichIni;	//Fichaje inicial
		private Time FichFin;	//Fichaje final
		private I_Turno turno;	//Identificador del turno
		
		/**
		 * Constructor
		 * @param tr objeto del que copiar los datos
		 */
		public I_Trabaja (Trabaja tr) {
			this.empl=vista.getEmpleado(tr.getIdEmpl());
			this.FichIni=tr.getFichIni();
			this.FichFin=tr.getFichFin();
			// Aquí hay que hacer una copia del turno
			this.turno = new I_Turno(vista.getTurno(tr.getIdTurno()));
		}
		
		/**
		 * Constructor de copia.
		 * @param tr 
		 */
		public I_Trabaja (I_Trabaja tr) {
			this.empl=new Empleado(tr.empl);
			this.FichIni=tr.getFichIni();
			this.FichFin=tr.getFichFin();
			// Aquí hay que hacer una copia del turno
			this.turno = new I_Turno(tr.getTurno());
		}
		
		/**
		 * Devuelve el Empleado.
		 * @return empl
		 */
		public Empleado getEmpl() {
			return empl;
		}
		
		/**
		 * Establece el empleado
		 * @param idEmpl
		 */
		public void setIdEmpl(Empleado idEmpl) {
			empl = idEmpl;
		}
		
		/**
		 * Devuelve el fichaje de entrada.
		 * @return FichIni
		 */
		public Time getFichIni() {
			return FichIni;
		}
		
		/**
		 * Establece el fichaje de entrada.
		 * @param fichIni
		 */
		public void setFichIni(Time fichIni) {
			FichIni = fichIni;
		}
		
		/**
		 * Devuelve el fichaje de salida.
		 * @return FichFin
		 */
		public Time getFichFin() {
			return FichFin;
		}
		
		/**
		 * Establece el fichaje de salida.
		 * @param fichFin
		 */
		public void setFichFin(Time fichFin) {
			FichFin = fichFin;
		}
		
		/**
		 * Devuelve el I_Turno.
		 * @return turno
		 */
		public I_Turno getTurno() {
			return turno;
		}		
		
		/**
		 * Establece el I_Turno.
		 * @param idTurno
		 */
		public void setIdTurno(I_Turno idTurno) {
			this.turno = idTurno;
		}
		
		/**
		 * Indica si el I_Turno ha sido modificado o no.
		 * @return cierto si el turno fue modificado, falso en cc
		 */
		public boolean isModificado() {
			return turno.isModificado();
		}
		
		/**
		 * Establece si el I_Turno ha sido modificado.
		 * @param modificado
		 */
		public void setModificado(boolean modificado) {
			turno.setModificado(modificado);
		}
	} //Fin I_Trabaja
	
	/** Vector donde en cada posición hay una lista de los empleados que trabajan */
	protected ArrayList<I_Trabaja> iCuad[];
	
	/**
	 * Constructor del cuadrante.
	 * @param vista				Puntero a la Vista
	 * @param mes				Mes representado por el cuadrante
	 * @param anio				Año representado por el cuadrante
	 * @param idDepartamento	Nombre del departamento representado
	 * @param subdivisiones		Número de subdivisiones que se muestran en el cuadrante.  
	 * 							<ul>
	 * 							<li>12	(cada 5 min),
	 * 							<li>6	(cada 10 min),
	 * 							<li>4	(cada 15 min),
	 * 							<li>2	(cada 30 min),
	 * 							<li>1	(sin subdivisiones)
	 * 							</ul>
	 * @param horaInicio		La hora a la que abre el departamento
	 * @param horaFin			La hora a la que cierra el departamento
	 */
	public I_Cuadrante(Vista vista, int mes, int anio, String idDepartamento, int subdivisiones, int horaInicio, int horaFin, ResourceBundle bundle) {
		super(mes, anio, idDepartamento);
		this.vista = vista;
		this.bundle = bundle;		
		Thread loader = new Loader();
		loader.start();
		setConfig(subdivisiones, horaInicio, horaFin);
		margenIzq = 15;
		margenDer = 20;
		margenSup = 1;
		margenInf = 10;
		margenNombres = 90;
		margenSupVistaMes=margenSup+30;
		departamento = idDepartamento;
		
		//Inicializar los arrays del calculo de los domingos
		meses31[0]=0;
		meses31[1]=1;
		meses31[2]=3;
		meses31[3]=5;
		meses31[4]=7;
		meses31[5]=8;
		meses31[6]=10;
		
		meses30[0]=4;
		meses30[1]=6;
		meses30[2]=9;
		meses30[3]=11;
		
		//Inicializar lista de empleados mostrados
		empleadosMostrados = new ArrayList<Empleado>();
	}
	
	/**
	 * Configura los márgenes del cuadrante sobre el canvas
	 * @param margenIzq		margen izquierdo
	 * @param margenDer		margen derecho 
	 * @param margenSup		margen superior
	 * @param margenInf		margen inferior
	 * @param margenNombres	margen que ocupan los nombres
	 */
	public void setMargenes(int margenIzq, int margenDer, int margenSup, int margenInf, int margenNombres) {
		this.margenIzq  = margenIzq;
		this.margenDer  = margenDer;
		this.margenSup  = margenSup;
		this.margenInf  = margenInf;
		this.margenNombres  = margenNombres;
		this.margenSupVistaMes=margenSup+30;
	}
	
	/**
	 * Configura el número de subdivisiones, la hora de apertura y la de cierre
	 * @param subdivisiones		número de subdivisiones
	 * @param horaInicio		la hora de apertura
	 * @param horaFin			la hora de cierre
	 */
	public void setConfig(int subdivisiones, int horaInicio, int horaFin) {
		this.horaApertura = horaInicio;
		this.horaCierre = horaFin;
		this.numSubdivisiones = subdivisiones;	
	}

	/**
	 * Coge los datos del cuadrante desde la cache.
	 */
	@SuppressWarnings("unchecked")
	public void actualizarDesdeCache() {
		try {
			// Si la caché principal está cargada, no estamos mostrando un interfaz para configurar un turno,
			// y la hora de la última actualización de caché difiere, entonces cargar datos
			if (actualizar() && turno==null && !timeLastUpdate.equals(vista.getTimeLastUpdate())) {
				cacheCargada = false;
				vista.setProgreso(vista.getBundle().getString("I02_lab_CargandoCuads"), 80);	// Mostrar mensaje de estado
				ArrayList<Trabaja> c[] = vista.getCuadrante(mes, anio, departamento).getCuad();	// Cargar cuadrante
				vista.setProgreso(null, 100);													// Quitar mensaje de estado
				if (primerCuad) {
					cuadInicialDeshacer = new Cuadrante(vista.getCuadrante(mes, anio, departamento));
					primerCuad = false;
				}
				iCuad = new ArrayList[c.length];
				for (int i=0; i<c.length; i++) {					// Copiar datos de la caché principal a la variable local
					iCuad[i] = new ArrayList<I_Trabaja>();			// para cada día,
					for (int j=0; j<c[i].size(); j++) {
						iCuad[i].add(new I_Trabaja(c[i].get(j)));				// y cada empleado
					}
				}
				cacheCargada = true;
				timeLastUpdate.setTime(vista.getTimeLastUpdate().getTime());	// Actualizar marca de tiempo
			}
			/* Recalcular tamaño del cuadrante */
			if (turno==null && !display.isDisposed()) {
				display.asyncExec(new Runnable() {
					public void run() {
						calcularTamano();
					}
				});
			}
		}
		catch (Exception e) {};
	}
	
	/**
	 * Prepara el interfaz para mostrar un solo turno.
	 * @param cCuadrante el composite sobre el que dibujar
	 */
	public void setCompositeUnTurno(Composite cCuadrante) {
		// Crear un turno por defecto para mostrar algo
		turno = new I_Turno(new Turno(0,"","","12:00:00","19:00:00","13:00:00",60,new Color(cCuadrante.getDisplay(),120,170,120)));
		margenNombres = 30;
		setComposite(cCuadrante, null, null, null, null, null, null);
		tipoVista = 2;
		setEnabled(true);
	}
	
	/**
	 * Devuelve el turno que se ha generado. 
	 * @return el turno generado
	 */
	public Turno getTurno() {
		return turno;
	}
	
	/**
	 * Asigna un turno para el interfaz de edición de un solo turno.
	 * @param t
	 */
	public void setTurno(Turno t) {
		turno = new I_Turno(t);
		redibujar();
	}
	
	/**
	 * Configura un composite para mostrar un cuadrante.
	 */
	public void setComposite(Composite cCuadrante, Button bPM, Button bPD, Button botonGuardar,Button botonDeshacer,Button botonRehacer,final DateTime calendario) {
//		alto_franjas = ALTO_FRANJAS_SHELL;
//		sep_vert_franjas = SEP_VERT_FRANJAS_SHELL;
		
		bPorMes=bPM;
		bPorDia=bPD;
		bGuardar = botonGuardar;
		bDeshacer = botonDeshacer;
		bRehacer = botonRehacer;
		cCuadrante.setLayout(new GridLayout(3,false));
		lCuadranteTitulo = new Label (cCuadrante, SWT.LEFT);
		String fname = lCuadranteTitulo.getFont().getFontData()[0].getName();
		lCuadranteTitulo.setFont(new Font(cCuadrante.getDisplay(),fname,15,0));

		lCuadranteTitulo.setText("");
		lCuadranteTitulo.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));

		lGridCuadrante= new Label (cCuadrante, SWT.LEFT);
		lGridCuadrante.setText(bundle.getString("I02_lab_intervalo"));
		lGridCuadrante.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));

		cGridCuadrante = new Combo(cCuadrante, SWT.BORDER | SWT.READ_ONLY);
		cGridCuadrante.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		cGridCuadrante.setItems(new String[] {"5 min", "10 min", "15 min", "30 min", "1h"});
		cGridCuadrante.select(2);

		cGridCuadrante.addListener(SWT.Selection, new Listener () {
			public void handleEvent (Event e){
				switch (cGridCuadrante.getSelectionIndex()) {
				case 0 : setNumSubdivisiones(12); calcularTamano(); break;
				case 1 : setNumSubdivisiones(6); calcularTamano(); break;
				case 2 : setNumSubdivisiones(4); calcularTamano(); break;
				case 3 : setNumSubdivisiones(2); calcularTamano(); break;
				case 4 : setNumSubdivisiones(1); calcularTamano(); 
				}
			}
		});

		// Preparar el canvas
		int opciones = SWT.FILL | SWT.NO_BACKGROUND;
		if (turno==null) opciones = SWT.FILL | SWT.NO_BACKGROUND | SWT.V_SCROLL;
		canvas = new Canvas(cCuadrante, opciones);
		canvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
		// Inicializar algunas variables
//		creando = false;
//		terminadoDeCrear = true;
		movimiento = 0;
		Thread animator = new Animator();
		animator.start();

		calcularTamano();
		display = canvas.getDisplay();
		paintListener = new PaintListener() {
			public void paintControl(PaintEvent event) {
				dibujarCuadrante(event.gc);
			}
		};
		canvas.addPaintListener(paintListener);
		canvas.addControlListener(new ControlListener() {
			public void controlMoved(ControlEvent e) {}
			public void controlResized(ControlEvent e) {
				calcularTamano();
			}
		});
		canvas.addMouseTrackListener(new MouseTrackListener(){
			public void mouseEnter(MouseEvent arg0) {}

			public void mouseExit(MouseEvent arg0) {
				if (cacheCargada) {
					empleadoActivo=-1;
					for (int i = 0; i < iCuad[dia-1].size(); i++) {
						iCuad[dia-1].get(i).getTurno().desactivarFranjas();
					}
					canvas.redraw();
				}
			}

			public void mouseHover(MouseEvent arg0) {}
			
		});
		
		vBar = canvas.getVerticalBar();
		if (vBar!=null) {
			vBar.setEnabled(false);
			vBar.addListener (SWT.Selection, new Listener () {
				public void handleEvent (Event e) {
					int vSelection = vBar.getSelection ();
					origen = -vSelection;
					canvas.redraw();
				}
			});
		}
		
		mouseMoveListenerCuadrDiario = new MouseMoveListener() {
			public void mouseMove(MouseEvent e) {
				actualizarDesdeCache();
				despMouse = Math.max(e.y - alto_franjas/2,margenSup+alto_franjas+sep_vert_franjas);
				if (moviendoEmpleado) {
					/*
					// asignarle la posición del empleado que está debajo
					
					int fila =  Math.round(e.y/(alto_franjas+sep_vert_franjas))-1;
					if (fila<0) fila=0;
					else if (fila>=empleadosMostrados.size())fila = empleadosMostrados.size()-1;
					
					// Intercambiar posiciones y reordenar datos
					if (empleadoActivo!=-1) {
						int posicionArriba = empleadosMostrados.get(empleadoActivo).getPosicion();
						if (posicionArriba!=0 && posicionArriba!=fila+1) {
							if (fila<posicionArriba-2) fila = posicionArriba-2;
							else if (fila>posicionArriba) fila = posicionArriba;
							empleadosMostrados.get(fila).setPosicion(posicionArriba);
							empleadosMostrados.get(posicionArriba-1).setPosicion(fila+1);
							empleadoActivo=fila;
							vista.ordenaEmpleados();
							if (bGuardar!=null) bGuardar.setEnabled(true);
						}
					}
					canvas.redraw();
					*/
				} else if (turno!=null || cacheCargada) {
				// Si estoy moviendo una franja
					if (dameMovimiento() == 2) {
						movimiento = turnoActivo.moverFranja(e.x, margenIzq, margenNombres, horaApertura, horaCierre, tamHora, tamSubdiv, numSubdivisiones);
						if (bGuardar!=null) bGuardar.setEnabled(true);
						canvas.redraw();
					}
				// Si estoy cambiando el inicio de una franja
				else if (dameMovimiento() == 1) {
					movimiento = turnoActivo.moverLadoIzquierdo(e.x, margenIzq, margenNombres, horaApertura, tamHora, tamSubdiv, numSubdivisiones);
					if (bGuardar!=null) bGuardar.setEnabled(true);
					canvas.redraw();
				}
				// Si estoy cambiando el fin de una franja
				else if (dameMovimiento() == 3) {
					movimiento = turnoActivo.moverLadoDerecho(e.x, margenIzq, margenNombres, horaApertura, horaCierre, tamHora, tamSubdiv, numSubdivisiones);
					if (bGuardar!=null) bGuardar.setEnabled(true);
					canvas.redraw();
				}
				// Si no estoy moviendo ninguna franja,
				// comprobar si el cursor está en alguna franja, una por una	
					else if (cacheCargada || turno != null){
						// Comprueba el empleado activo (vertical)
						int i = 0;
						Boolean encontrado = false;
						Boolean redibujar = false;
						if (turno==null) {
							int empleadoActivoNuevo = -1;
							// Seleccionar empleado activo

							while (!encontrado && i < iCuad[dia-1].size()) { 
								if (iCuad[dia-1].get(i).turno.contienePunto(e.y-origen, i,margenSup,sep_vert_franjas,alto_franjas))
									empleadoActivoNuevo = i;
								i++;
							}
							
							if (empleadoActivoNuevo != empleadoActivo) {
								empleadoActivo = empleadoActivoNuevo;
								redibujar = true;
							}

							// Comprueba la franja activa (horizontal)
							i = 0;
							encontrado = false;
						}
						if (turnoActivo != null) turnoActivo.desactivarFranjas();
						I_Turno t;
						if (turno==null) {
							if (!empleadosMostrados.isEmpty()){
								while (!encontrado && i < iCuad[dia-1].size()) {
									t = iCuad[dia-1].get(i).getTurno();
									if (empleadoActivo==-1) { cursor(0); t.desactivarFranjas(); }
									else if (iCuad[dia-1].get(i).getEmpl()!=null && 
											iCuad[dia-1].get(i).getEmpl().getEmplId() ==
												empleadosMostrados.get(empleadoActivo).getEmplId()) {
										if 		(t.contienePixelInt(e.x))	{ cursor(1); encontrado = true; turnoActivo = t; redibujar=true;}// trasteando++;}
										else if (t.tocaLadoIzquierdo(e.x))	{ cursor(2); encontrado = true; turnoActivo = t; redibujar=true;}
										else if (t.tocaLadoDerecho(e.x))	{ cursor(2); encontrado = true; turnoActivo = t; redibujar=true;}
//										else if (e.x < margenNombres)		{ cursor(3); encontrado = true; turnoActivo = null; redibujar=true;}
										else 								{ cursor(0); }
									}
									i++;
								}
							}
						} else {
							if 		(turno.contienePixelInt(e.x))	{ cursor(1); encontrado = true; turnoActivo = turno; redibujar=true;}// trasteando++;}
							else if (turno.tocaLadoIzquierdo(e.x))	{ cursor(2); encontrado = true; turnoActivo = turno; redibujar=true;}
							else if (turno.tocaLadoDerecho(e.x))	{ cursor(2); encontrado = true; turnoActivo = turno; redibujar=true;}
							//else if (e.x < margenNombres)			{ cursor(3); encontrado = true; turnoActivo = null; redibujar=true;}
							else 									{ cursor(0); }

						}
						if (!encontrado && turnoActivo!=null) { cursor(0); turnoActivo=null; redibujar=true; }
						if (redibujar) canvas.redraw();
						// Si el usuario está haciendo el memo con las barritas
//						if (trasteando==400) {
//							MessageBox messageBox = new MessageBox(canvas.getShell(),
//									SWT.APPLICATION_MODAL | SWT.YES | SWT.NO);
//							messageBox.setText("Pesao");
//							messageBox.setMessage("¿Quieres dejarlo ya?");
//							messageBox.open();
//							trasteando=0;
//						}
					}
				}
			}
		};
		
		mouseListenerCuadrDiario = new MouseListener() {
			public void mouseDown(MouseEvent e) {
				// Botón derecho: Borra una franja o inserta un descanso 
				// (podría mostrar un menú si hace falta)
				if (turnoActivo!=null && e.button == 3) {
					turnoActivo.botonSecundario(e.x, margenIzq, margenNombres, horaApertura, tamHora, tamSubdiv, numSubdivisiones);
					if (bGuardar!=null) bGuardar.setEnabled(true);
					canvas.redraw();
				} else if (turnoActivo!=null && e.button == 1) {
					movimiento = turnoActivo.botonPrimario(e.x, margenIzq, margenNombres, horaApertura, tamHora, tamSubdiv, numSubdivisiones);
				}// else if (e.x < margenNombres) moviendoEmpleado = true;
			}
			
			public void mouseUp(MouseEvent e) {
				movimiento=0;
				moviendoEmpleado = false;
				canvas.redraw();
			}
			
			public void mouseDoubleClick(MouseEvent e) {
			/*	int i = 0;
				FranjaDib f;
				Boolean encontrado = false;
				while (!encontrado
						&& i < cuadrante.empleados.get(empleadoActivo).turno.franjas
								.size()) {
					f = cuadrante.empleados.get(empleadoActivo).turno.franjas.get(i);
					if (f.contienePixelInt(e.x)) {
						f = cuadrante.empleados.get(empleadoActivo).turno.franjas
								.get(i);
						// Franja f2 = cuadrante.new Franja (f.inicio, e.x-10);
						// f.inicio=e.x+10;
						// cuadrante.empleados.get(empleadoActivo).franjas.add(f2);
						redibujar();
						encontrado = true;
					}
					i++;
				}*/
			}
		};
		
		mouseListenerCuadrMensual = new MouseListener() {
			public void mouseDown(MouseEvent e){
				//calcularPosRatonMensual(e);
				if (menuContAbierto) menuContAbierto = false;
				else {
					if (e.button == 1 &&(diaValido)) {//&& diaActVistaMes<iCuad.length && empActVistaMes<iCuad[diaActVistaMes].size()) {
						if (turnoSeleccionado==null) {	
							turnPulsX=diaActVistaMes;
							turnPulsY=empActVistaMes;
							//turnoPulsado=true;
							cursor(1);
						}
						empleadoSeleccionado = iCuad[diaActVistaMes].get(indiceEmpAct).getEmpl();
						turnoSeleccionado = iCuad[diaActVistaMes].get(indiceEmpAct).getTurno();
						casillaSeleccionada = iCuad[diaActVistaMes].get(indiceEmpAct);
					} else if (e.button == 1 &&(nombreValido)) {
						if (nombreSeleccionado==null)
							nombreMarcado=empActVistaMes;
						nombreSeleccionado=vista.getEmpleados().get(empActVistaMes).getNombre();
						cursor(3);
						// Mostrar menú contextual si se pulsa el botón derecho
					} else if (e.button == 3 && enCuadricula) {
						//calcularPosRatonMensual(e);
						final int diaActVistaMesLocal = diaActVistaMes;
						final int indiceEmpActLocal = indiceEmpAct;
						final int empActVistaMesLocal = empActVistaMes;
						Menu menuContextual = new Menu(canvas.getShell(), SWT.BORDER);
						// Items para asignar los distintos turnos
						if (diaValido) {
							empleadoSeleccionadoSec = iCuad[diaActVistaMesLocal].get(indiceEmpActLocal).getEmpl();
							int idTurnoEmp = iCuad[diaActVistaMesLocal].get(indiceEmpActLocal).getTurno().getIdTurno();
							for (int i=0; i<empleadoSeleccionadoSec.getContrato(vista).getNumTurnosContrato().size(); i++){
								final int idTurno = empleadoSeleccionadoSec.getContrato(vista).getNumTurnosContrato().get(i);
								if (idTurnoEmp != idTurno) {
									MenuItem item = new MenuItem(menuContextual, SWT.CASCADE);
									item.setText(bundle.getString("I02_asignar")+" "+vista.getTurno(idTurno).getDescripcion());
									item.addSelectionListener(new SelectionListener() {
										public void widgetSelected(SelectionEvent arg0) {
											pushCuadranteDeshacer();
											Trabaja t = new Trabaja(empleadoSeleccionadoSec.getEmplId(), new Time(0,0,0),  new Time(0,0,0), idTurno);
											iCuad[diaActVistaMesLocal].set(indiceEmpActLocal, new I_Trabaja(t));
											menuContAbierto = false;
											cuadAcache();
											cuadModificado = true;
											if (bGuardar!=null) bGuardar.setEnabled(true);
											if (bDeshacer!=null) bDeshacer.setEnabled(true);
											if (bRehacer!=null) bRehacer.setEnabled(false);
											calcularTamano();
										}
										public void widgetDefaultSelected(SelectionEvent arg0) {}
									});
								}
							}
							MenuItem item = new MenuItem(menuContextual, SWT.CASCADE);
							item.setText(bundle.getString("I02_asignar_dia_libre"));
							item.addSelectionListener(new SelectionListener() {
								public void widgetSelected(SelectionEvent arg0) {
									pushCuadranteDeshacer();
									iCuad[diaActVistaMesLocal].remove(indiceEmpActLocal);
									menuContAbierto = false;
									cuadAcache();
									cuadModificado = true;
									if (bGuardar!=null) bGuardar.setEnabled(true);
									if (bDeshacer!=null) bDeshacer.setEnabled(true);
									if (bRehacer!=null) bRehacer.setEnabled(false);
									calcularTamano();
								}
								public void widgetDefaultSelected(SelectionEvent arg0) {}
							});
						}
						else {
							empleadoSeleccionadoSec = vista.getEmpleados().get(empActVistaMesLocal);
							for (int i=0; i<empleadoSeleccionadoSec.getContrato(vista).getNumTurnosContrato().size(); i++){
								final int idTurno = empleadoSeleccionadoSec.getContrato(vista).getNumTurnosContrato().get(i);
								MenuItem item = new MenuItem(menuContextual, SWT.CASCADE);
								try {
									item.setText(bundle.getString("I02_asignar")+" "+vista.getTurno(idTurno).getDescripcion());
									item.addSelectionListener(new SelectionListener() {
										public void widgetSelected(SelectionEvent arg0) {
											pushCuadranteDeshacer();
											Trabaja t = new Trabaja(empleadoSeleccionadoSec.getEmplId(), new Time(0), new Time(0), idTurno);
											iCuad[diaActVistaMesLocal].add(new I_Trabaja(t));
											menuContAbierto = false;
											cuadAcache();
											cuadModificado = true;
											if (bGuardar!=null) bGuardar.setEnabled(true);
											if (bDeshacer!=null) bDeshacer.setEnabled(true);
											if (bRehacer!=null) bRehacer.setEnabled(false);
											calcularTamano();
										}
										public void widgetDefaultSelected(SelectionEvent arg0) {}
									});
								}
								catch (Exception ee){
									System.err.println(ee.getMessage());
								}
							}
						}
						menuContAbierto = true;
						canvas.setMenu(menuContextual);
					} /*else if (e.button == 3 && !enCuadro) {
						if (cuadModificado) {
							Menu menuContextual = new Menu(canvas.getShell(), SWT.BORDER);
							MenuItem item = new MenuItem(menuContextual, SWT.CASCADE);
							item.setText("Deshacer cambios");
							item.addSelectionListener(new SelectionListener() {
								public void widgetSelected(SelectionEvent arg0) {
									deshacerICuad();
									cuadModificado = false;
									menuContAbierto = false;
									if (bGuardar!=null) bGuardar.setEnabled(false);
									calcularTamano();
								}
								public void widgetDefaultSelected(SelectionEvent arg0) {}
							});
							menuContAbierto = true;
							canvas.setMenu(menuContextual);
						}
					}*/
					else  
						canvas.setMenu(null);
						//empleadoSeleccionadoSec=null;
				}
			};
			
			public void mouseUp(MouseEvent e){
				if (e.button == 1 && diaValido && turnoSeleccionado!=null) { //&& diaActVistaMes<iCuad.length && empActVistaMes<iCuad[diaActVistaMes].size()) {
					Turno turnoSeleccionado2=iCuad[diaActVistaMes].get(indiceEmpAct).getTurno();
					//Si los turnos a intercambiar son distintos
					if(turnoSeleccionado.getIdTurno()!=turnoSeleccionado2.getIdTurno()) {
						//Si los dos empleados tienen el mismo contrato
						if (empleadoSeleccionado.getContratoId() ==
							iCuad[diaActVistaMes].get(indiceEmpAct).getEmpl().getContratoId()) {
							MessageBox messageBox = new MessageBox(canvas.getShell(),
									SWT.APPLICATION_MODAL | SWT.YES | SWT.NO);
							messageBox.setText(bundle.getString("Aviso"));
							String nombre1 = empleadoSeleccionado.getNombre();
							String nombre2 = iCuad[diaActVistaMes].get(indiceEmpAct).getEmpl().getNombre();
							if (nombre1 != nombre2)
								messageBox.setMessage(bundle.getString("I02_intercambiar_turno_2emp_a")+" "+nombre1+" "+
										bundle.getString("I02_intercambiar_turno_2emp_b")+" "+nombre2+"?");
							else
								messageBox.setMessage(bundle.getString("I02_intercambiar_turno_1emp")+" "+nombre1+"?");
							if (messageBox.open()==SWT.YES) {
								pushCuadranteDeshacer();
								// Intercambiar turnos
								Turno.intercambiar(turnoSeleccionado, turnoSeleccionado2);
								cuadAcache();
								cuadModificado = true;
								//establecerCuad(1);
								if (bGuardar!=null) bGuardar.setEnabled(true);
								if (bDeshacer!=null) bDeshacer.setEnabled(true);
								if (bRehacer!=null) bRehacer.setEnabled(false);
								calcularTamano();				
							}
						}
						else {
							MessageBox messageBox = new MessageBox(canvas.getShell(),
									SWT.APPLICATION_MODAL | SWT.OK );
							messageBox.setText(bundle.getString("Error"));
							messageBox.setMessage(bundle.getString("I02_no_intercambiar_turnos"));
							messageBox.open();
						}
					}					
				}
				if (e.button == 1 && !diaValido && enCuadricula && turnoSeleccionado!=null) {
					ArrayList<Empleado> empleados = vista.getEmpleados();
					//empleados.remove(0);
					aplicacion.datos.Empleado emp2=empleados.get(empActVistaMes);
					//Comprobamos que los empleados tengan el mismo contrato
					if (empleadoSeleccionado.getContratoId() == emp2.getContratoId()){
						MessageBox messageBox = new MessageBox(canvas.getShell(),
								SWT.APPLICATION_MODAL | SWT.YES | SWT.NO);
						messageBox.setText(bundle.getString("Aviso"));
						String nombre1 = empleadoSeleccionado.getNombre();
						String nombre2 = emp2.getNombre();
						if (nombre1 != nombre2) 
							messageBox.setMessage(bundle.getString("I02_intercambiar_turno_2emp_a")+" "+nombre1+" "+
									bundle.getString("I02_intercambiar_turno_libre_2emp_b")+" "+nombre2+"?");
						else
							messageBox.setMessage(bundle.getString("I02_intercambiar_turno_2emp_a")+" "+nombre1+" "+
									bundle.getString("I02_intercambiar_turno_libre_1emp_b"));
						if (messageBox.open()==SWT.YES) {
							pushCuadranteDeshacer();
							// Intercambiar turnos
							iCuad[turnPulsX].remove(casillaSeleccionada);
							casillaSeleccionada.setIdEmpl(emp2);
							iCuad[diaActVistaMes].add(casillaSeleccionada);
							//
							//algoritmo.Cuadrante cuadranteSel=vista.getCuadrante(mes, anio, departamento);
							cuadAcache();
							cuadModificado = true;
							//establecerCuad(1);
							//algoritmo.Cuadrante cuadrante=new Cuadrante(mes,anio,departamento);
							//
							if (bGuardar!=null) bGuardar.setEnabled(true);
							if (bDeshacer!=null) bDeshacer.setEnabled(true);
							if (bRehacer!=null) bRehacer.setEnabled(false);
							calcularTamano();				
						}
					}
					else {
						MessageBox messageBox = new MessageBox(canvas.getShell(),
								SWT.APPLICATION_MODAL | SWT.OK );
						messageBox.setText(bundle.getString("Error"));
						messageBox.setMessage(bundle.getString("I02_no_intercambiar_turnos"));
						messageBox.open();
					}
				}
				turnoSeleccionado = null;
				if (e.button == 1 && nombreSeleccionado!=null && nombreMarcado!=empActVistaMes) {
					ArrayList<Empleado> empleados = vista.getEmpleados();
//					int posEmpSel;
					int posEmpADesp;
					int contEmp;
					aplicacion.datos.Empleado empSel = empleados.get(nombreMarcado);
					aplicacion.datos.Empleado empADesp = empleados.get(empActVistaMes);
					aplicacion.datos.Empleado empADespAux = null;
//					posEmpSel = empSel.getPosicion();
					posEmpADesp = empADesp.getPosicion();
					empSel.setPosicion(posEmpADesp);
					empSel.setModificado(true);
					empleados.set(empActVistaMes, empSel);
					if (nombreMarcado < empActVistaMes) {
						empADesp.setPosicion(posEmpADesp-1);
						empADesp.setModificado(true);
						contEmp=empActVistaMes-1;
						empADespAux = empleados.get(contEmp);
						empleados.set(contEmp, empADesp);
						contEmp--;
						for (int i = 0;contEmp>=nombreMarcado;i++) {
							if (i % 2 == 0) {
								posEmpADesp = empADespAux.getPosicion();
								empADespAux.setPosicion(posEmpADesp-1);
								empADespAux.setModificado(true);
								empADesp = empleados.get(contEmp);
								empleados.set(contEmp, empADespAux);	
							}
							else {
								posEmpADesp = empADesp.getPosicion();
								empADesp.setPosicion(posEmpADesp-1);
								empADesp.setModificado(true);
								empADespAux = empleados.get(contEmp);
								empleados.set(contEmp, empADesp);
							}
							contEmp--;
						}
					}
					else {
						empADesp.setPosicion(posEmpADesp+1);
						empADesp.setModificado(true);
						contEmp=empActVistaMes+1;
						empADespAux = empleados.get(contEmp);
						empleados.set(contEmp, empADesp);
						contEmp++;
						for (int i = 0;contEmp<=nombreMarcado;i++) {	
							if (i % 2 == 0) {
								posEmpADesp = empADespAux.getPosicion();
								empADespAux.setPosicion(posEmpADesp+1);
								empADespAux.setModificado(true);
								empADesp = empleados.get(contEmp);
								empleados.set(contEmp, empADespAux);	
							}
							else {
								posEmpADesp = empADesp.getPosicion();
								empADesp.setPosicion(posEmpADesp+1);
								empADesp.setModificado(true);
								empADespAux = empleados.get(contEmp);
								empleados.set(contEmp, empADesp);
							}
							contEmp++;
						}
					}
					if (bGuardar!=null) bGuardar.setEnabled(true);
					//if (bDeshacer!=null) bDeshacer.setEnabled(true);
					calcularTamano();
				}
				nombreSeleccionado=null;
				
				if (e.button == 3 && menuContAbierto) {
					canvas.setMenu(null);
				}
				//turnoPulsado=false;
				canvas.redraw();
			};
			
			public void mouseDoubleClick(MouseEvent e){
				if (e.button == 1 &&(enCuadricula)) {
					//Volver a la vista diaria con el dia seleccionado
					tipoVista=2;
					setListenersTipoVista(2);
					cursor(0);
					bPorMes.setSelection(false);
					bPorDia.setSelection(true);
					setDia(diaActVistaMes+1);
					//System.out.println("Dia "+diaActVistaMes);
					calendario.setDay(diaActVistaMes+1);
					diaValido=false;
					turnoSeleccionado=null;
				}
			};
		};
		mouseMoveListenerCuadrMensual = new MouseMoveListener() {
			public void mouseMove(MouseEvent e) {
				calcularPosRatonMensual(e);
			}
		};
	}
	
	/**
	 * Método que testea la posición del cursor en el cuadrante mensual,
	 * activando o desactivando los flags involucrados, que acabarán indicando
	 * a la apliación la decisión tomada por el usuario en los eventos de ratón.
	 * @param e
	 */
	public void calcularPosRatonMensual(MouseEvent e) {
		if (cacheCargada) {
			//Comprueba si el cursor esta situado sobre algun dia
			cursor.x = e.x; cursor.y = e.y-origen;
			diaValido = false;
			int dia = 0;
			Boolean diaEncontrado = false;
			int inicioX = margenNombres + margenIzq;
			int anchoMes = anchoImagen - margenIzq - margenDer - margenNombres;
			int anchoDia = anchoMes / iCuad.length;
			int anchoDiaCont=0;
			while (!diaEncontrado && (dia < iCuad.length)) {
				// Calculamos la franja horizontal de cada dia
				if (e.x > (inicioX + anchoDiaCont + 1)
						&& e.x < (inicioX + anchoDiaCont + anchoDia - 1)) {
					diaActVistaMes = dia;
					diaEncontrado = true;
				}
				anchoDiaCont += anchoDia;
				dia++;
			}
			//Comprueba si el cursor esta situado sobre algun empleado
			int iEmp = 1;
			Boolean empEncontrado = false;
			ArrayList<Empleado> empleados = vista.getEmpleados();
			//empleados.remove(0);
			int altoFila = 20;
			int altoFilaCont = 0;
			int inicioY = margenSupVistaMes + altoFila;
			while (!empEncontrado && (iEmp < empleados.size())) {
				// Calculamos la franja vertical de cada empleado
				if (cursor.y > (inicioY + altoFilaCont + 1)
						&& cursor.y < (inicioY + altoFilaCont + altoFila - 1)) {
					empActVistaMes = iEmp;
					empEncontrado = true;
				}
				altoFilaCont += altoFila;
				iEmp++;
			}
			if (empEncontrado && diaEncontrado) {
				if (empTrabDia(diaActVistaMes, empleados.get(empActVistaMes).getEmplId()) && nombreSeleccionado==null) {
					cursor(1);
					diaValido = true;
				} else {
					cursor(0);
					diaValido = false;
				}
				enCuadricula=true;
			} else {
				cursor(0);
				diaValido = false;
				enCuadricula=false;
			}
			//Comprobamos si el cursor está dentro de cuadro de los cuadrantes
			/*if ((e.x > inicioX && e.x < (inicioX + anchoDiaCont)) &&
					(cursor.y > inicioY && cursor.y < inicioY + altoFilaCont))
				enCuadro=true;
			else
				enCuadro=false;*/
			//Comprobamos si el cursor se encuentra sobre el nombre de algún empleado
			//Primero comprobamos la franja vertical de ancho margenNombres
			Boolean enFranjaVert=false;
			if (e.x>margenIzq+1 && e.x<margenIzq+margenNombres-25)
				enFranjaVert=true;
			if (enFranjaVert && empEncontrado && turnoSeleccionado==null) {
				cursor(3);
				nombreValido = true;
			}
			else {
				if (!diaValido) {
					cursor(0);
				}
				nombreValido = false;
			}
			if (nombreSeleccionado!=null) cursor(3);
			if (turnoSeleccionado!=null) cursor(1);
			canvas.redraw();
		}
	}
	
	/**
	 * Devuelve el valor del atributo movimiento
	 * @return movimiento
	 */
	private int dameMovimiento() {
		return movimiento;
	}
	
	/**
	 * Método que llama a los "dibujaCuadranteDia" y "dibujaCuadranteMes" dependiendo del
	 * valor del atributo "tipoVista".
	 * @param gc contenedor gráfico
	 */
	private void dibujarCuadrante(GC gc) {
		// Doble buffering para evitar parpadeo
		if (anchoImagen != 0 && altoImagen != 0) {
			Image bufferImage = new Image(display, anchoImagen, altoImagen);
			GC gc2 = new GC(bufferImage);
			if (alto_franjas>15)
				gc2.setFont(new Font(display,"Verdana",alto_franjas/2,SWT.BOLD));

			try {
				gc2.setAntialias(SWT.ON);
			}
			catch (SWTException ex){
				vista.infoErrorDebug(this, String.valueOf(ex.code));
			}
			if (tipoVista==2) 
				dibujarCuadranteDia(gc2);
			else
				dibujarCuadranteMes(gc2);
			gc.drawImage(bufferImage, 0, origen);
			bufferImage.dispose();
		}
	}
	
	/**
	 * Establece las subdivisiones del cuadrante diario.
	 * @param i		nº de subdivisiones
	 */
	private void setNumSubdivisiones(int i) {
		numSubdivisiones = i;
		tamSubdiv = tamHora/numSubdivisiones;
		redibujar();
	}
	
	/**
	 * Establece el día.
	 * @param dia
	 */
	public void setDia(int dia){
		this.dia = dia;
		if (actualizar()) {
			actualizarDesdeCache();
			redibujar();			
		}
	};
	
	/**
	 * Establece el día y obtiene las sugerencias correspondientes al mismo.
	 * @param dia	dia a establecer
	 * @param mes	mes a establecer
	 * @param anio	año a establecer
	 * @return	s String con el conjunto de sugerencias
	 */
	public String setDiaYGetSugerencia(int dia, int mes, int anio) {
		this.dia = dia;
		this.mes = mes;
		this.anio = anio;
		String s = null;
		if (!departamento.isEmpty()) {
			try {
				ArrayList<Sugerencia> sugs = vista.getSugerenciasDia(dia, mes, anio, departamento);
				if (sugs.size() > 0){
					s = "";
					for (int i=0; i<sugs.size(); i++)
						s += sugs.get(i).getSugerencia() + "\n";
				}
			}
			catch(Exception e) {System.err.println(bundle.getString("I02_no_sugerencias"));}
		}
		if (actualizar()) {
			timeLastUpdate=new java.util.Date(0);
			actualizarDesdeCache();
			redibujar();
		}
		return s;
	}
	
	/**
	 * Asigna el departamento que queremos ver y carga el cuadrante 
	 * @param departamento
	 */
	public void setDepartamentoYCarga(String departamento) {
		this.departamento = departamento;
		if (actualizar()) {
			actualizarDesdeCache();
			redibujar();
		}
	}
	
	/**
	 * Calcula el tamaño de las franjas cuando se redimensiona la ventana.
	 */
	private void calcularTamano() {
		sep_vert_franjas = 10;
		alto_franjas = 15;
		if (!canvas.isDisposed()) {
		anchoImagen = canvas.getClientArea().width;
		int altoVentana = canvas.getClientArea().height;
		int altoDatos = (vista.getEmpleadosDepartamento(departamento).size()+1) * (alto_franjas + sep_vert_franjas);
		altoImagen = Math.max(altoDatos, altoVentana);
		if (vBar!=null) {
//			System.out.println("Origen      : " + origen);
//			System.out.println("Alto imagen : " + altoImagen);
//			System.out.println("Alto ventana: " + altoVentana);
			if (altoVentana>altoImagen) {
				vBar.setSelection(0);
				vBar.setEnabled(false);
				origen=0;
			} else if (altoVentana-origen>altoImagen) {
				origen=altoVentana-altoImagen;
				vBar.setSelection(origen);				
			} else {
				vBar.setEnabled(true);
				vBar.setMaximum(altoImagen-altoVentana);
			}
		}
		setTamano(anchoImagen, altoImagen);
		if (turno!=null)
			turno.recalcularFranjas(margenIzq, margenNombres, horaApertura, tamHora);
		else if (cacheCargada && tipoVista==2) {
			for (int i = 0; i < iCuad[dia-1].size(); i++) {
				if (iCuad[dia-1].get(i).getTurno()==null) 
					System.out.println(bundle.getString("I02_turno_nulo")+" "+ dia +
							bundle.getString("I02_posicion")+" "+ i);
				iCuad[dia-1]
				      .get(i)
				      .getTurno()
				      .recalcularFranjas(margenIzq, margenNombres, horaApertura, tamHora);
			}
		}
		fondo = null; // El fondo que hay ya no vale, hay que redibujarlo
		}
	}
	
	/**
	 * Calcula el tamaño del área a imprimir.
	 * @param ancho
	 * @param alto
	 */
	private void calcularTamanoParaImprimir(int ancho, int alto) {
		if (!canvas.isDisposed()) {
			margenNombres = ancho/5;
			setTamano(ancho, alto);
			// Calcular la altura vertical de cada franja
			sep_vert_franjas = Math.round(alto / vista.getEmpleados().size() * 60/100);
			alto_franjas = Math.round(alto / vista.getEmpleados().size() * 40/100);
			
			// Calcular el tamaño del texto
			if (cacheCargada && tipoVista==2) {
				for (int i = 0; i < iCuad[dia-1].size(); i++) {
					if (iCuad[dia-1].get(i).getTurno()==null) 
						System.out.println(bundle.getString("I02_turno_nulo")+" "+ dia +
								bundle.getString("I02_posicion")+" "+ i);
					iCuad[dia-1]
					      .get(i)
					      .getTurno()
					      .recalcularFranjas(margenIzq, margenNombres, horaApertura, tamHora);
				}
			}
			fondo = null; // El fondo que hay ya no vale, hay que redibujarlo
		}
	}

	/**
	 * Método para repintar el cuadrante cuando se han hecho cambios.
	 */
	public void redibujar() {
		// Redibuja sólo las franjas que corresponden, para evitar calculos
		// innecesarios
		// c.redraw(0, margenSup+(sep_vert_franjas+alto_franjas)*(posV+1),
		// ancho, 18, false);
		// c.redraw(0, 0, ancho, alto, false);
		if (display!=null && !display.isDisposed()) {
			display.asyncExec(new Runnable() {
				public void run() {
					if (!canvas.isDisposed()) {
						canvas.redraw();
						if (turno==null)
							if (tipoVista==2)
								lCuadranteTitulo.setText(String.valueOf(dia) + " " + bundle.getString("I02_horariode") + " " + aplicacion.utilidades.Util.mesAString(vista.getBundle(), mes-1) + " " + bundle.getString("I02_horariode") + " " + String.valueOf(anio));
							else
								lCuadranteTitulo.setText(aplicacion.utilidades.Util.mesAString(vista.getBundle(), mes-1).substring(0,1).toUpperCase()+
										aplicacion.utilidades.Util.mesAString(vista.getBundle(), mes-1).substring(1)+ " " + bundle.getString("I02_horariode") + " " + String.valueOf(anio));
					}
				}
			});
		}
	}
	
	/**
	 * Dibuja el cuadrante, resaltando el empleado activo.
	 * @param gc				El GC del display sobre el que se dibujará el cuadrante.
	 * @param empleadoActivo	La posición del empleado a resaltar en la lista de empleados.
	 */
	public void dibujarCuadranteDia(GC gc) {
		
//		Long i = new Date().getTime();
//		dibujarSeleccion(gc, empleadoActivo);
//		Long j = new Date().getTime();
		actualizarFondo(gc);
//		Long k = new Date().getTime();
		dibujarTurnos(gc);
//		Long l = new Date().getTime();
//		vista.infoDebug("I_Cuadrante", "Tiempos dibujo: \n" +
//				String.valueOf(j-i) + " ms. dibujar seleccion\n" +
//				String.valueOf(k-j) + " ms. dibujar horas\n" + 
//				String.valueOf(l-k) + " ms. dibujar turnos\n");
		if (turno==null && tipoImpresion==0)
			dibujarLineaDistribucion(gc);
	}
	
	/**
	 * Dibuja las barras que representan las franjas horarias que trabaja cada empleado.
	 * @param gc	El GC del display sobre el que se dibujará el cuadrante.
	 */
	public void dibujarTurnos(GC gc) {
		if (turno!=null) {			
			turno.dibujar(display, "", gc, 0, turno.getColor(), margenIzq, margenNombres,margenSup,sep_vert_franjas,alto_franjas,tamHora, tamSubdiv, horaApertura, numSubdivisiones,0, tipoImpresion!=0);
			moviendoPestanas = turno.getEstadoPestana();
		} else if (cacheCargada) {
/*			for (int i = 0; i < iCuad[dia-1].size(); i++) {
				// Dibujar el nombre del empleado y el turno
				String nombre = iCuad[dia-1].get(i).getEmpl().getNombre().charAt(0) + ". " + iCuad[dia-1].get(i).getEmpl().getApellido1();
				int desp = 0;
				if (moviendoEmpleado && empleadoActivo == i)
					desp = despMouse;  
				iCuad[dia-1].get(i).getTurno().
				dibujar(display, nombre, gc, i, iCuad[dia-1].get(i).getEmpl().dameColor(), margenIzq, margenNombres, margenSup, sep_vert_franjas, alto_franjas, tamHora, tamSubdiv, horaApertura, numSubdivisiones, desp);	
			}
*/
			int fila = 0;
			empleadosMostrados.clear();
			boolean b = false;
			for ( int i=0; i<vista.getEmpleados().size(); i++) {
			// Dibujar el nombre del empleado y el turno
				String nombre = vista.getEmpleados().get(i).getNombre().charAt(0) + ". " + vista.getEmpleados().get(i).getApellido1();			
				int desp = 0;
				if (moviendoEmpleado && empleadoActivo == fila)
					desp = despMouse;  
				for (int j = 0; j < iCuad[dia-1].size(); j++) {
					// Si el empleado está en la caché (puede estar en el cuadrante, pero haber sido dado de baja)
					if (vista.getEmpleados().get(i)!=null &&
							iCuad[dia-1].get(j).getEmpl()!=null && 
							vista.getEmpleados().get(i).getEmplId() == iCuad[dia-1].get(j).getEmpl().getEmplId()) {
						empleadosMostrados.add(vista.getEmpleados().get(i));
						iCuad[dia-1].get(j).getTurno().dibujar(display, nombre, gc, fila, empleadosMostrados.get(fila).getColor() ,margenIzq, margenNombres,margenSup,sep_vert_franjas,alto_franjas,tamHora, tamSubdiv, horaApertura, numSubdivisiones, desp, tipoImpresion!=0);
						if (iCuad[dia-1].get(j).getTurno().getEstadoPestana()) {
							b = true; 
						}
						fila++;
//					} else if (moviendoEmpleado) {
//						empleadosMostrados.add(vista.getEmpleados().get(i));
//						fila++;
					}
				}
			}
			moviendoPestanas = b;
		}
	}
	
	/**
	 * Dibuja una caja con información sobre el turno del empleado, cuando el cursor se encuentra
	 * encima de alguna casilla válida, pulsándola además. También dibuja un botón centrado en el
	 * cursor cuando se ha seleccionado alguna casilla, para arrastrarlo a otro empleado.
	 * @param gc	El GC del display sobre el que se dibujará el cuadrante.
	 */
	public void dibujarCuadranteMes(GC gc) {
		if (fondo==null)
			actualizarFondo(gc);
		else gc.drawImage(fondo, 0, 0);
		
		int inicioY=margenSupVistaMes+altoFila;
		//Sacamos la informacion del turno
		
		if (turnoSeleccionado!=null) {
			dibujaBotonPuls(gc,margenIzq+margenNombres+((turnPulsX)*anchoDia),
					inicioY+((turnPulsY-1)*altoFila),anchoDia,altoFila);
		}
		
		if (diaValido) { //&& diaActVistaMes<iCuad.length && empActVistaMes<iCuad[diaActVistaMes].size()){
			//Sacamos la informacion del turno
			int idTurno=iCuad[diaActVistaMes].get(indiceEmpAct).getTurno().getIdTurno();
			//Obtenemos el color de relleno a partir de él
			//Color colorTurno=obtenColor(idTurno);
			//Color colorTurno=iCuad[diaActVistaMes].get(indiceEmpAct).getTurno().getColor();
			Color colorTurno=iCuad[diaActVistaMes].get(indiceEmpAct).getTurno().getColor();
			//Obtenemos las cadenas a mostrar
			String idTurnoS=(bundle.getString("I02_id_turno")+": "+String.valueOf(idTurno));
			String descTurno=iCuad[diaActVistaMes].get(indiceEmpAct).getTurno().getDescripcion();
			int ancho=Math.max(gc.textExtent(descTurno).x+15,gc.textExtent(idTurnoS).x+15);
			//Alto de la caja
			int alto=gc.textExtent(descTurno).y+gc.textExtent(idTurnoS).y+12;
			//Información del color
			//Color color = new Color(display,120,170,120);
			int r = colorTurno.getRed();
			int g = colorTurno.getGreen();
			int b = colorTurno.getBlue();
			//Pintamos segun turno
			int inicioX=margenIzq+margenNombres+10-(ancho/2);
			//canvas.
			Util.cambiarRelleno(display, gc, r-50,g-50,b-50);
			gc.fillRectangle(inicioX+((diaActVistaMes)*anchoDia),
					inicioY+((empActVistaMes-1)*altoFila)-alto,ancho,alto);
			Util.cambiarRelleno(display, gc, r,g,b);
			//Util.cambiarPincel(display, gc, r-100,g-100,b-100);
			gc.setForeground(Util.getColorDiferenciado(colorTurno, 100));
			gc.fillRectangle(inicioX+((diaActVistaMes)*anchoDia)-2,
					inicioY+((empActVistaMes-1)*altoFila)-(alto+2),ancho-2,alto-2);
			gc.drawRectangle(inicioX+((diaActVistaMes)*anchoDia)-2,
					inicioY+((empActVistaMes-1)*altoFila)-(alto+2),ancho-2,alto-2);
			gc.drawText(idTurnoS,
					inicioX+((diaActVistaMes)*anchoDia)+2,
					inicioY+((empActVistaMes-1)*altoFila)-alto+2,altoFila);
			gc.drawText(descTurno,
					inicioX+((diaActVistaMes)*anchoDia)+2,
					inicioY+((empActVistaMes-1)*altoFila)-(alto-(altoFila)),altoFila);
			
			//Util.darBrillo(display, gc, r, g, b,30);
			dibujaBotonPuls(gc,margenIzq+margenNombres+((diaActVistaMes)*anchoDia),
					inicioY+((empActVistaMes-1)*altoFila),anchoDia,altoFila);
			//System.out.println("Act. Dia: "+diaActVistaMes+" Long. dia: "+iCuad[diaActVistaMes].size()+" Empleado: "+iCuad[diaActVistaMes].get(empActVistaMes).getEmpl().getNombre());
		}
		
		if (turnoSeleccionado!=null) {
			//Sacamos la informacion del turno
			String abr=turnoSeleccionado.getAbreviatura();
			if (abr == null) abr = "";
			//Obtenemos el color de relleno a partir de él
			//Color colorTurno=obtenColor(abr);
			//turnoSeleccionado.setColor(color7M);
			//Color colorTurno=turnoSeleccionado.getColor();
			Color colorTurno=turnoSeleccionado.getColor();
			gc.setBackground(colorTurno);
			gc.setForeground(Util.getColorDiferenciado(colorTurno, 100));
			//gc.drawRectangle(cursor.x-anchoDia/2, cursor.y-altoFila/2, anchoDia, altoFila);
			gc.fillRectangle(cursor.x-anchoDia/2, cursor.y-altoFila/2, anchoDia, altoFila);
			if (anchoDia>gc.textExtent(abr).x-2)
				gc.drawText(abr,cursor.x-anchoDia/2 + (7/2),cursor.y - altoFila/2 + 2,altoFila);
			dibujaBoton(gc,cursor.x-anchoDia/2,cursor.y-altoFila/2,anchoDia,altoFila);
			gc.setBackground(new Color(display,255,255,255));
		}
		
		if (nombreSeleccionado!=null){
			gc.setBackground(Util.getColorDiferenciado(azulClar, 120));
			gc.setForeground(azulClar);
			String nomSel=vista.getEmpleados().get(nombreMarcado).getNombre();
			gc.drawRectangle(margenIzq-7,inicioY+((nombreMarcado-1)*altoFila), maxLongNombre+15, gc.textExtent(nomSel).y+2);
			gc.fillRectangle(margenIzq-6,inicioY+((nombreMarcado-1)*altoFila)+1, maxLongNombre+14, gc.textExtent(nomSel).y+1);
			//gc.setForeground(negro);
			gc.drawText(nomSel,margenIzq+2,inicioY+((nombreMarcado-1)*altoFila)+2);
		}
		
		if (nombreValido || nombreSeleccionado!=null) {
			gc.setBackground(Util.getColorDiferenciado(azulClar, 120));
			gc.setForeground(azulClar);
			String nomSel=vista.getEmpleados().get(empActVistaMes).getNombre();
			gc.drawRectangle(margenIzq-7,inicioY+((empActVistaMes-1)*altoFila), maxLongNombre+15, gc.textExtent(nomSel).y+2);
			gc.fillRectangle(margenIzq-6,inicioY+((empActVistaMes-1)*altoFila)+1, maxLongNombre+14, gc.textExtent(nomSel).y+1);
			//gc.setForeground(negro);
			gc.drawText(nomSel,margenIzq+2,inicioY+((empActVistaMes-1)*altoFila)+2);
		}
		
		if (nombreSeleccionado!=null){
			gc.setBackground(Util.getColorDiferenciado(azulOsc, 120));
			gc.setForeground(azulOsc);
			gc.drawRectangle(margenIzq+17,cursor.y-(altoFila-4)/2-5, maxLongNombre+15,gc.textExtent(nombreSeleccionado).y+2);
			gc.fillRectangle(margenIzq+18,cursor.y-(altoFila-4)/2+1-5, maxLongNombre+14,gc.textExtent(nombreSeleccionado).y+1);
			//String nomSel=vista.getEmpleados().get(empActVistaMes).getNombre();
			//gc.setForeground(negro);
			gc.drawText(nombreSeleccionado,margenIzq+26,cursor.y-(altoFila-4)/2+2-5);
		}
	}
	
	/**
	 * Dibuja lineas verticales representando las horas y las subdivisiones del cuadrante en la
	 * vista diaria. En la vista mensual se encarga de dibujar una red de casillas que representan
	 * los días que trabaja cada empleado de un departamento al mes, junto con su identificador de
	 * turno.
	 * @param gc	El GC del display sobre el que se dibujará el cuadrante.
	 */
	private void actualizarFondo(GC gc) {
		int m = margenIzq + margenNombres;
		int h = horaCierre - horaApertura;
		sep = (anchoImagen - m - margenDer)/h;
		int subsep = sep/numSubdivisiones;
		if (fondo == null && (tipoImpresion==2 || tipoVista==2)) {
			fondo = new Image(display,anchoImagen,altoImagen);
			GC gcFondo = new GC(fondo);
			if (alto_franjas>15) {
				gcFondo.setFont(new Font(display,"Verdana",alto_franjas/2,SWT.BOLD));
				gcFondo.setLineWidth(alto_franjas/15);
			}

			if (!enabled && tipoImpresion==0) {
				gcFondo.setBackground(display.getSystemColor(SWT.COLOR_TITLE_INACTIVE_BACKGROUND));
				gcFondo.fillRectangle(0,0,anchoImagen,altoImagen);
			}
			for (int i=0; i<=h; i++) {
				gcFondo.setLineStyle(SWT.LINE_SOLID);
				gcFondo.setForeground(new Color(display,40,80,40));
				if (sep>14 && sep<=20) gcFondo.drawText(String.valueOf((horaApertura+i)%24), m+i*sep-gc.textExtent(String.valueOf((horaApertura+i)%24)).x/2, margenSup, true);
				else if (sep>20)     gcFondo.drawText(String.valueOf((horaApertura+i)%24)+'h', m+i*sep-gc.textExtent(String.valueOf((horaApertura+i)%24)+'h').x/2, margenSup, true);
				gcFondo.drawLine(m+i*sep, gc.textExtent("A").y + margenSup, m+i*sep, altoImagen-margenInf);
				gcFondo.setForeground(new Color(display, 120,170,120));
				gcFondo.setLineStyle(SWT.LINE_DOT);
				if (i!=h)
					for (int j=1; j<numSubdivisiones; j++) {
						gcFondo.drawLine(m+i*sep+j*subsep, gc.textExtent("A").y*5/4 + margenSup, m+i*sep+j*subsep, altoImagen-margenInf-gc.textExtent("A").y/4);
					}
			}
			gcFondo.setLineStyle(SWT.LINE_SOLID);
		} else if (fondo==null && (tipoImpresion!=2 && tipoVista!=2)) {
			if (cacheCargada){
				fondo = new Image(display,anchoImagen,altoImagen);
				GC gcFondo = new GC(fondo);						
				Calendar c = Calendar.getInstance();
				// Esto coge el primer domingo
				boolean domingoEncontrado = false;
				int dom = 1;
				c.set(anio,mes,1);
				//System.out.println(c.get(Calendar.YEAR));
				while (!domingoEncontrado) {
					//Dependiendo del mes en el que se encuentre el domingo tendra un valor u otro
					if (c.get(Calendar.DAY_OF_WEEK)==4 && esMes31(c.get(Calendar.MONTH))) domingoEncontrado=true;
					else if ((c.get(Calendar.DAY_OF_WEEK)==3 && esMes30(c.get(Calendar.MONTH)))) domingoEncontrado=true;
					else if ((c.get(Calendar.DAY_OF_WEEK)==2 && c.get(Calendar.MONTH)==2 && c.get(Calendar.YEAR)%4==0)) domingoEncontrado=true;
					else if ((c.get(Calendar.DAY_OF_WEEK)==1 && c.get(Calendar.MONTH)==2 && c.get(Calendar.YEAR)%4!=0)) domingoEncontrado=true;
					else {
						dom++;
						c.roll(Calendar.DATE, true);
						//c.set(anio,mes,dom);
					}
				}
				int anchoMes = anchoImagen - margenIzq - margenDer - margenNombres;
				anchoDia = anchoMes/iCuad.length;
				altoFila = 20;
				// Dibujar números de los días
				if (anchoDia>14)
					for (int j=0; j < iCuad.length; j++) {
						if (((j+1)-dom)%7==0) gcFondo.setForeground(new Color(display,255,0,0));
						else if (((j+1)-dom)%7==1) gcFondo.setForeground(new Color(display,0,0,0));
						gcFondo.drawText(String.valueOf(j+1), margenIzq + margenNombres + j*anchoDia + 
								(anchoDia/2 - gcFondo.textExtent(String.valueOf(j+1)).x/2), margenSupVistaMes);
						gcFondo.setForeground(new Color(display,0,0,0));
					}
				gcFondo.setForeground(azulOsc);
				gcFondo.drawText(bundle.getString("Empleados"), margenIzq , margenSupVistaMes);
				gcFondo.setForeground(new Color(display,0,0,0));
				ArrayList<Empleado> empleados=vista.getEmpleados();
				int limI=0;
				for (int i=1; i < empleados.size(); i++) {
					aplicacion.datos.Empleado e=empleados.get(i);
					gcFondo.drawText(e.getNombre(), margenIzq, margenSupVistaMes + 20 + (i-1)*altoFila);
					if (gcFondo.textExtent(e.getNombre()).x > maxLongNombre)
						maxLongNombre=gcFondo.textExtent(e.getNombre()).x;
					for (int j=0; j < iCuad.length; j++) {
						//Despues calculamos el turno a visualizar
						Boolean encontrado=false;
						int k=0;
						while (!encontrado && k<iCuad[j].size()) {
							if (iCuad[j].get(k).getEmpl().getEmplId()==e.getEmplId()) {	
								dibujaCasilla(gcFondo, i-1, j, k, new Color(display,120,170,120));
								encontrado=true;
							}
							k++;
						}
						if (!encontrado)
							dibujaCasillaVacia(gcFondo, i-1, j, blanco,anchoDia,altoFila);
						//System.out.println("Dia: "+j+" Long. dia: "+iCuad[j].size());
					}
					limI=i;
				}
				//Leyenda de los colores
				
				if (anchoDia>12 && altoFila>12) {
					
					int despX=margenIzq;
					String j="Jefe";
					//gcFondo.drawText(j,despX,margenSupVistaMes + 20 + (limI+1)*altoFila);
					despX+=(gcFondo.textExtent(j).x+4);
					//gcFondo.setBackground(azulOsc);
					//gcFondo.fillRectangle(despX, margenSupVistaMes + 20 + (limI+1)*altoFila, anchoDia-5,altoFila-5);
					despX+=(anchoDia-5+15);
					//gcFondo.setBackground(blanco);
					
					ArrayList<Turno> turnos=vista.getTurnos();
					boolean v1=false;
					boolean v2=false;
					for (int i=0;i<turnos.size()-1;i+=2) {
						if (!turnos.get(i).getDescripcion().substring(0,2).equals("TE")) {
							gcFondo.drawText(turnos.get(i).getDescripcion(),despX,margenSupVistaMes + 20 + (limI+1)*altoFila);
							v1=true;
						}
						if (!turnos.get(i+1).getDescripcion().substring(0,2).equals("TE")) {
							gcFondo.drawText(turnos.get(i+1).getDescripcion(),despX,margenSupVistaMes + 23 + (limI+2)*altoFila);
							v2=true;
						}	
						if (v1&&v2)
							despX+=(Math.max(gcFondo.textExtent(turnos.get(i).getDescripcion()).x,
									gcFondo.textExtent(turnos.get(i+1).getDescripcion()).x)+4);
						else
							if (v1) despX+=gcFondo.textExtent(turnos.get(i).getDescripcion()).x+4;
							else if (v2) despX+=gcFondo.textExtent(turnos.get(i+1).getDescripcion()).x+4;
						if (v1) {	
							gcFondo.setBackground(turnos.get(i).getColor());
							gcFondo.fillRectangle(despX, margenSupVistaMes + 20 + (limI+1)*altoFila, anchoDia-5,altoFila-5);
						}
						if (v2) {
							gcFondo.setBackground(turnos.get(i+1).getColor());
							gcFondo.fillRectangle(despX, margenSupVistaMes + 23 + (limI+2)*altoFila, anchoDia-5,altoFila-5);
						}	
							despX+=(anchoDia-5+15);
							gcFondo.setBackground(blanco);
						v1=false;
						v2=false;
					}
					
					/**
					String m4="4h Mañana";
					gcFondo.drawText(m4,despX,margenSupVistaMes + 20 + (limI+1)*altoFila);
					gcFondo.drawText("4h Tarde",despX,margenSupVistaMes + 23 + (limI+2)*altoFila);
					despX+=(gcFondo.textExtent(m4).x+4);
					gcFondo.setBackground(color4M);
					gcFondo.fillRectangle(despX, margenSupVistaMes + 20 + (limI+1)*altoFila, anchoDia-5,altoFila-5);
					gcFondo.setBackground(color4T);
					gcFondo.fillRectangle(despX, margenSupVistaMes + 23 + (limI+2)*altoFila, anchoDia-5,altoFila-5);
					despX+=(anchoDia-5+15);
					gcFondo.setBackground(blanco);
					
					String mS="Sábado Mañana";
					gcFondo.drawText(mS,despX,margenSupVistaMes + 20 + (limI+1)*altoFila);
					gcFondo.drawText("Sábado Tarde",despX,margenSupVistaMes + 23 + (limI+2)*altoFila);
					despX+=(gcFondo.textExtent(mS).x+4);
					gcFondo.setBackground(colorSM);
					gcFondo.fillRectangle(despX, margenSupVistaMes + 20 + (limI+1)*altoFila, anchoDia-5,altoFila-5);
					gcFondo.setBackground(colorST);
					gcFondo.fillRectangle(despX, margenSupVistaMes + 23 + (limI+2)*altoFila, anchoDia-5,altoFila-5);
					despX+=(anchoDia-5+15);
					gcFondo.setBackground(blanco);
					*/
				}
			}
		}
		if (fondo!=null)
		gc.drawImage(fondo,0,0);
	}
	
	/**
	 * Dibuja una casilla vacia en la posición marcada por i y j dentro de los márgenes.
	 * @param gc		Contenedor gráfico en el que se dibujará la casilla.
	 * @param i			Contador de filas o empleados.
	 * @param j			Contador de columnas o días.
	 * @param color		Color para el relleno de la casilla.
	 */
	public void dibujaCasillaVacia(GC gc, int i, int j, Color color,int ancho,int alto){
		gc.setBackground(color);
		gc.setForeground(negro);
		gc.drawRectangle(margenIzq + margenNombres + j*anchoDia, margenSupVistaMes + 20 + i*altoFila, ancho, alto);
		gc.fillRectangle(margenIzq + margenNombres + j*anchoDia+1, margenSupVistaMes + 20 + i*altoFila+1,ancho-1,alto-1);
		gc.setBackground(blanco);
	}
	
	/**
	 * Dibuja una casilla en la posición marcada por i y j dentro de los márgenes, si es que se
	 * trata de una casilla en blanco. Si la casilla corresponde a un empleado con un turno en ese
	 * día, escribe también su identificador, y la rellena del color indicado por parámetro.
	 * @param gc		Contenedor gráfico en el que se dibujará la casilla.
	 * @param i			Contador de filas o empleados.
	 * @param j			Contador de columnas o días.
	 * @param empl		Entero que representa al empleado del que se obtendrá el turno a mostrar.
	 * @param color		Color para el relleno de la casilla.
	 */
	public void dibujaCasilla(GC gc, int i, int j, int empl, Color color){
		//Obtenemos el identificador de turno del empleado que le toca ese día
		String abr = iCuad[j].get(empl).getTurno().getAbreviatura();
		if (abr == null) abr = "";
		//Obtenemos el color de relleno a partir de él
		//Color colorTurno=obtenColor(idTurno);
		
		Color colorTurno=iCuad[j].get(empl).getTurno().getColor();
		//vista.getTurno(idTurno);
//		colorTurno = vista.getTurno(idTurno).getColor();
		//Primero se pinta el rectangulo
		
		gc.setForeground(Util.getColorDiferenciado(colorTurno, 100));
		gc.drawRectangle(margenIzq + margenNombres + j*anchoDia, margenSupVistaMes + 20 + i*altoFila, anchoDia, altoFila);

		gc.setBackground(colorTurno);
		gc.fillRectangle(margenIzq + margenNombres + j*anchoDia+1, margenSupVistaMes + 20 + i*altoFila+1, anchoDia-1, altoFila-1);
		//gc.setForeground(new Color(display,0,0,0));
		if (anchoDia>gc.textExtent(abr).x-2)
			//gc.drawText(String.valueOf(iCuad[j].get(k).getTurno().getAbreviatura().charAt(0)),margenIzq + margenNombres + j*anchoDia + (7/2), margenSup + 20 + i*altoFila + 2,altoFila);
			gc.drawText(abr,
					margenIzq + margenNombres + j*anchoDia + (anchoDia/2 - gc.textExtent(String.valueOf(abr)).x/2),
					margenSupVistaMes + i*altoFila + 23,altoFila);
				
		gc.setBackground(new Color(display,255,255,255));
		gc.setForeground(new Color(display,0,0,0));
	}
	
	/**
	 * Dibuja un botón en la posición marcada por iX y iY, de tamaño especificado por ancho y alto.
	 * @param gc		Contenedor gráfico en el que se dibujará el botón.
	 * @param iX		Coordenada X.
	 * @param iY		Coordenada Y.
	 * @param ancho 	Ancho.
	 * @param alto		Alto.
	 */
	public void dibujaBoton(GC gc,int iX,int iY,int ancho,int alto) {
		//Lineas grises
		gc.setForeground(new Color(display,210,210,210));
		//Vertical
		gc.drawLine(iX,iY,iX,iY+alto);
		//Horizontal
		gc.drawLine(iX,iY,iX+ancho,iY);
		//Lineas negras
		gc.setForeground(new Color(display,50,50,50));
		//Vertical
		gc.drawLine(iX+ancho,iY,iX+ancho,iY+alto);
		//Horizontal
		gc.drawLine(iX+1,iY+alto,iX+ancho-1,iY+alto);
	}
	
	/**
	 * Dibuja un botón pulsado en la posición marcada por iX y iY, de tamaño especificado por ancho
	 * y alto.
	 * @param gc		Contenedor gráfico en el que se dibujará el botón.
	 * @param iX		Coordenada X.
	 * @param iY		Coordenada Y.
	 * @param ancho 	Ancho.
	 * @param alto		Alto.
	 */
	public void dibujaBotonPuls(GC gc,int iX,int iY,int ancho,int alto) {
		//Lineas grises
		gc.setForeground(new Color(display,50,50,50));
		//Vertical
		gc.drawLine(iX,iY,iX,iY+alto);
		//Horizontal
		gc.drawLine(iX,iY,iX+ancho,iY);
		//Lineas negras
		gc.setForeground(new Color(display,210,210,210));
		//Vertical
		gc.drawLine(iX+ancho,iY,iX+ancho,iY+alto);
		//Horizontal
		gc.drawLine(iX,iY+alto,iX+ancho,iY+alto);
		gc.setForeground(new Color(display,0,0,0));
	}
	
	/**
	 * Dibuja un fondo distinguido para el empleado seleccionado, basado en el color del empleado
	 * pero más pálido.
	 * @param gc	El GC sobre el que resaltar el empleado.
	 * @param emp	La posición del empleado a resaltar en la lista de empleados. Se considera
	 * 				que -1 significa que no hay ningún empleado seleccionado.
	 */
	private void dibujarSeleccion (GC gc, int emp) {
		if (emp!=-1) {
			Color color = new Color(display,220,240,220);
			if (vista.getEmpleados().get(emp).getColor()!=null)
				color = new Color(display, 255-(255-vista.getEmpleados().get(emp).getColor().getRed())/5, 255-(255-vista.getEmpleados().get(emp).getColor().getGreen())/5, 255-(255-vista.getEmpleados().get(emp).getColor().getBlue())/5);
			gc.setBackground(color);
			gc.fillRectangle(Math.max(margenIzq-2,0),margenSup+(sep_vert_franjas+alto_franjas)*(emp+1)-5,anchoImagen-margenIzq-margenDer,alto_franjas+11);
		}
	}
	
	/**
	 * Pega el valor x al más cercano dentro de la rejilla. El tamaño de la rejilla está determinado
	 * por el número de subdivisiones.
	 * @param x		El valor a ajustar.
	 * @return		El valor ajustado a la rejilla.
	 */
	public Posicion sticky (int x) {
		int y = x - margenNombres - margenIzq + (tamHora/numSubdivisiones)/2;
		Posicion p;
		if (((y%tamHora)/(tamHora/numSubdivisiones))>=numSubdivisiones)
			// Para evitar resultados del tipo 14:60
			p = new Posicion(1+y/tamHora+horaApertura,0);
		else
			// En otro caso, hay que tener en cuenta cómo se dibuja el cuadrante para evitar
			// desfases entre las lineas horarias y las franjas.
			p = new Posicion(y/tamHora+horaApertura,((y%tamHora)/(tamHora/numSubdivisiones))*12/numSubdivisiones);
		return p;
	}
	
	/**
	 * Actualiza el tamaño del cuadrante, el tamaño de las horas y las subdivisiones, y para cada
	 * franja, actualiza sus píxeles inicial y final en función de sus valores pinicio y pfin.
	 * @param ancho	El ancho nuevo, en píxeles.
	 * @param alto	El alto nuevo, en píxeles.
	 */
	public void setTamano(int ancho, int alto) {
		this.altoImagen = alto;
		this.anchoImagen = ancho;
		tamHora = (ancho - margenIzq-margenDer-margenNombres)/(horaCierre-horaApertura);
		tamSubdiv = tamHora/numSubdivisiones;
	}
	
	/**
	 * Cambia la forma del cursor según el parámetro escrito.
	 * @param i		Entero con el cursor a mostrar:<br>
	 * <ul>				
	 * <li>0: Arrow</li>
	 * <li>1: Hand</li>
	 * <li>2: Size E</li>
	 * <li>3: Size All</li>
	 * <li>4: Wait</li>
	 * </ul>
	 */
	private void cursor(int i) {
		if (canvas!=null)
			switch (i) {
			case 1:
				canvas.setCursor(new Cursor(canvas.getDisplay(), SWT.CURSOR_HAND));
				break;
			case 2:
				canvas.setCursor(new Cursor(canvas.getDisplay(), SWT.CURSOR_SIZEE));
				break;
			case 3:
				canvas.setCursor(new Cursor(canvas.getDisplay(), SWT.CURSOR_SIZEALL));
				break;
			case 4:
				canvas.setCursor(new Cursor(canvas.getDisplay(), SWT.CURSOR_WAIT));
				break;
			default:
				canvas.setCursor(new Cursor(canvas.getDisplay(), SWT.CURSOR_ARROW));
				break;
			}
	}
	
	/**
	 * Establece el atributo que controla la vista a mostrar. True para la vista diaria y False para
	 * la mensual.
	 * @param d		booleano con el valor a establecer.
	 */
	public void setDiario(boolean d) {
		if (d) {
			tipoVista = 2;
			setListenersTipoVista(2);
		} else {
			tipoVista = 1;
			setListenersTipoVista(1);
		}
		fondo = null;
		calcularTamano();
		redibujar();
	}
	
	/**
	 * Activa/desactiva las acciones del raton sobre los cuadrantes diarios y mensuales.
	 * @param i 	Define qué cambio realizar:<br>
	 * 				0 desactiva listeners<br>
	 * 				1 activa listeners mensuales (desactiva diarios)<br>
	 * 				2 activa listeners diarios (desactiva mensuales)
	 */
	public void setListenersTipoVista(int i) {
		switch (i) {
		case 1:
			if (mouseMoveListenerCuadrDiario	!= null) canvas.removeMouseMoveListener(mouseMoveListenerCuadrDiario);
			if (mouseListenerCuadrDiario		!= null) canvas.removeMouseListener(mouseListenerCuadrDiario);
			canvas.addMouseMoveListener(mouseMoveListenerCuadrMensual);
			canvas.addMouseListener(mouseListenerCuadrMensual);
			//Ocultamos el combo de los intervalos
			//lCuadranteTitulo.setVisible(false);
			lGridCuadrante.setVisible(false);
			cGridCuadrante.setVisible(false);
			bDeshacer.setVisible(true);
			bRehacer.setVisible(true);
			tipoVista = 1;
			break;
		case 2: 
			if (mouseMoveListenerCuadrMensual	!= null) canvas.removeMouseMoveListener(mouseMoveListenerCuadrMensual);
			if (mouseListenerCuadrMensual		!= null) canvas.removeMouseListener(mouseListenerCuadrMensual);
			canvas.addMouseMoveListener(mouseMoveListenerCuadrDiario);
			canvas.addMouseListener(mouseListenerCuadrDiario);
			//lCuadranteTitulo.setVisible(true);
			lGridCuadrante.setVisible(true);
			cGridCuadrante.setVisible(true);
			bDeshacer.setVisible(false);
			bRehacer.setVisible(false);
			this.calcularTamano();
			tipoVista = 2;
			/*if (cuadModificado) {
				MessageBox messageBox = new MessageBox(canvas.getShell(),
						SWT.APPLICATION_MODAL | SWT.YES | SWT.NO);
				messageBox.setText("Atencion");
				messageBox.setMessage("¿Desea guardar los cambios efectuados en el cuadrante" +
						" antes de pasar a la vista diaria?");
				if (messageBox.open()==SWT.YES) {
					guardarCambios();
					if (bGuardar!=null) bGuardar.setEnabled(false);
					if (bDeshacer!=null) bDeshacer.setEnabled(false);
				}
				else {
					//Comprobar que tiene que coger el Cuadrante 0 como
					//cuadrante mas antiguo a deshacer
					if (!pilaCuadsDeshacer.isEmpty()) {
						pilaCuadsRehacer.push(deICuadACuadrante());
						deshacerICuad(pilaCuadsDeshacer.get(0));
						pilaCuadsDeshacer.removeAllElements();
					}
					else
						deshacerICuad(cuadInicialDeshacer);
					if (bGuardar!=null) bGuardar.setEnabled(false);
					if (bDeshacer!=null) bDeshacer.setEnabled(false);
					cuadModificado = false;
				}
			}*/
			break;
		default:
			if (canvas!=null) {
				if (mouseMoveListenerCuadrMensual	!= null) canvas.removeMouseMoveListener(mouseMoveListenerCuadrMensual);
				if (mouseListenerCuadrMensual		!= null) canvas.removeMouseListener(mouseListenerCuadrMensual);
				if (mouseMoveListenerCuadrDiario	!= null) canvas.removeMouseMoveListener(mouseMoveListenerCuadrDiario);
				if (mouseListenerCuadrDiario		!= null) canvas.removeMouseListener(mouseListenerCuadrDiario);
			}
			break;
		}
	}
	
	/**
	 * Método para la vista mensual que indica si el cursor está encima de alguna casilla con un
	 * turno activo.
	 * @param dia		Día en el que hay que buscar dentro de iCuad.
	 * @param idEmpl	Empleado del que se desea saber si trabaja ese día.
	 * @return			True si el cursor se situa sobre alguna zona válida.
	 */
	public boolean empTrabDia(int dia,int idEmpl){
		Boolean encontrado=false;
		int i=0;
		while (!encontrado && i<iCuad[dia].size()){
			if (iCuad[dia].get(i).getEmpl().getEmplId()==idEmpl) {
				encontrado=true;
				indiceEmpAct=i;
			}
			i++;
		}
		return encontrado;
	}
	
	/**
	 * Comprueba si un mes tiene 31 días.
	 * @param mes	Mes a comprobar.
	 * @return 		True si el mes es de 31 días.
	 */
	public boolean esMes31(int mes){
		boolean encontrado=false;
		int i=0;
		while (!encontrado && i<7){
			if (mes==meses31[i]) encontrado=true;
			else i++;
		}
		return encontrado;
	}
	
	/**
	 * Comprueba si un mes tiene 30 días.
	 * @param mes	Mes a comprobar.
	 * @return 		True si el mes es de 30 días.
	 */
	public boolean esMes30(int mes){
		boolean encontrado=false;
		int i=0;
		while (!encontrado && i<4){
			if (mes==meses30[i]) encontrado=true;
			else i++;
		}
		return encontrado;
	}
	
	/**
	 * Devuelve el color perteneciente al turno seleccionado.
	 * @param idTurno	Turno a comprobar.
	 * @return 			Color del turno.
	 */
	public Color obtenColor(int idTurno){
		Color result;
		switch (idTurno) {
			case 120: result=azulOsc; break;
			default: result=azulOsc; break;
		}
		return result;
	}
	
	/**
	 * Calcula la longitud máxima de los nombres de la lista de "empleados".
	 * @param empleados		Lista a examinar.
	 * @return 				Longitud máxima en un entero.
	 */
	public int obtenMaxNombre(GC gc,ArrayList<Empleado> empleados){
		int max=0;
		for (int i=1;i<empleados.size();i++) {
			if (max < gc.textExtent(empleados.get(i).getNombre()).x){
				max=gc.textExtent(empleados.get(i).getNombre()).x;
			}
			i++;
		}
		return max;
	}
	
	/**
	 * 
	 * @return
	 */
	public boolean isEnabled() {
		return enabled;
	}
	
	/**
	 * 
	 * @param enabled
	 */
	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
		if (enabled) {
			setListenersTipoVista(tipoVista);
			cursor(0);
			if (vBar!=null) vBar.setEnabled(false);
		}
		else {
			setListenersTipoVista(0);
			cursor(4);
			if (vBar!=null) vBar.setEnabled(true);
		}
		fondo=null;
		if (canvas!=null) canvas.redraw();
	}
	
	/**
	 * Guarda los cambios realizados sobre el cuadrante en la BD
	 */
	public boolean guardarCambios() {
		cursor(4);
		I_Trabaja t;
		Empleado e;
		boolean correcto = true;
		if (!correcto) return false;
		//Guardar el cuadrante en la base de datos
		if (cuadModificado) {
			cuadABD(1);
			cuadModificado = false;
			//if (!historialPilas.getPilaCuadsRehacer().isEmpty()) {
			//	historialPilas.getPilaCuadsRehacer().removeAllElements();
			//}
		}
		// Mirar qué turnos se han modificado
		for (int i=0; i<iCuad[dia-1].size(); i++) {
			t = iCuad[dia-1].get(i);
			// Si el turno se ha modificado, hay que insertarlo en la BD como uno nuevo
			if (t.isModificado()) {
				int idEmpl = iCuad[dia-1].get(i).getEmpl().getEmplId();
				// Se inserta el turno nuevo con una descripción diferente
				Turno tr = new Turno(t.getTurno());
				tr.setDescripcion("TE-" + idEmpl + "@" + aplicacion.utilidades.Util.fechaAString(dia, mes, anio));
				int idTurno = vista.insertTurno(tr);
				// Se asigna el turno al empleado para el día correspondiente
				correcto &= vista.modificarTrabaja(idTurno, idEmpl, dia, mes, anio, departamento);
			}	
		}
		// Mirar qué empleados se han modificado
		for (int i=0; i<vista.getEmpleados().size(); i++) {
			e = vista.getEmpleados().get(i);
			if (e.isModificado()) {
				correcto &= vista.modificarEmpleado(e);
				e.setModificado(false);
			}
		}
		if (!correcto) return false;
		
		cursor(0);
		return correcto;
	}
	
	/**
	 * Indica si se ha tocado algo en el cuadrante
	 * @return <i>true</i> si se ha desplazado algún empleado o se ha modificado algún turno
	 */
	public boolean isModificado() {
		boolean modificado = false;
		if (cacheCargada) {
			// Mirar si se ha cambiado algún empleado de posición
			if (tipoVista==2)
				for (int i=0; i<vista.getEmpleados().size(); i++)
					if (vista.getEmpleados().get(i).isModificado())
						modificado = true;

			// Mirar si se ha modificado algún turno
			for (int i=0; i<iCuad[dia-1].size(); i++) 
				if (iCuad[dia-1].get(i).isModificado())
					modificado = true;
		}
		return modificado;
	}

	public ImageData getDrawableImage() {
		return null;
	}
	
	/**
	 * 
	 */
	public ImageData getPrintableImage(Device device, ResourceBundle bundle,
			Rectangle size, boolean bn) {
		canvas.removePaintListener(paintListener);
		int w = size.width/2;
		int h = size.height/3;
		Image image = new Image(device, w, h);
		GC gc = new GC(image);
		
		calcularTamanoParaImprimir(w,h);
		int tipoVistaAux = tipoVista; 
		if (tipoImpresion==1) {
			tipoVista = 1;
		} else {
			tipoVista = 2;
		}
		
		dibujarCuadrante(gc);
		tipoVista = tipoVistaAux;
		tipoImpresion = 0;
		canvas.addPaintListener(paintListener);
		canvas.redraw();
		margenNombres = 90;
		return image.getImageData();
	}

	/**
	 * Elige el tipo de vista para imprimir: 1 vista mensual, 2 vista diaria.
	 * @param tipoImpresion
	 */
	public void setTipoImpresion(int tipoImpresion) {
		this.tipoImpresion = tipoImpresion;
	}
	
	/**
	 * Añade información debajo del cuadrante diario acerca de la gente que trabaja en cada franja
	 */
	public void dibujarLineaDistribucion(GC gc) {
		// Dibujar la linea abajo del canvas
		int altoTexto = gc.textExtent("0").y ;
		int y = canvas.getSize().y - altoTexto - origen;
//		Calendar c = Calendar.getInstance();
		// y = margenSup + (empleadosMostrados.size()+2) * (sep_vert_franjas + alto_franjas);
		gc.setBackground(new Color(display,255,255,255));
		gc.setForeground(new Color(display,40,80,40));
		gc.drawLine(0, y-1, anchoImagen, y-1);
		try {
			gc.setAlpha(128);
		} catch (Exception e) {}
		gc.fillRectangle(0 , y, anchoImagen, altoTexto);
		try {
			gc.setAlpha(255);
		} catch (Exception e) {}
		// Para cada hora mostrar cuántos empleados trabajan (redondear por abajo)
		int personasCurrando, personasCurrandoHorasCompletas;//, tipoDia, min, max;
//		min = 0; max = 0;
		for (int i=horaApertura; i<horaCierre; i++) {
			personasCurrando = 0;
			personasCurrandoHorasCompletas = 0;
//			c.set(anio, mes, dia);
//			tipoDia = c.get(Calendar.DAY_OF_WEEK);
			// Comparar con la distribución (que va a ser que no)
			/*
			ArrayList<Object[]> o = vista.getDistribucionDepartamentoDiaSemana(departamento, 1);
			if (o!=null && !o.isEmpty()) {
				min = (Integer)o.get(0)[0];
				max = (Integer)o.get(0)[1];
			}*/
			boolean cabeTodo = sep >= gc.textExtent("0-0").x+10;
			int posTexto;
			if (cabeTodo) posTexto = gc.textExtent("0-0").x/2;
			else posTexto = gc.textExtent("0").x/2;
			for (int j=0; j<empleadosMostrados.size(); j++) {
				if (iCuad[dia-1].get(j).getTurno().estaTrabajando(i,true)) personasCurrando++;
				if (cabeTodo && iCuad[dia-1].get(j).getTurno().estaTrabajando(i,false)) personasCurrandoHorasCompletas++;
			}
			gc.setBackground(new Color(display, 255, 255, 255));
			//gc.drawText(String.valueOf(personasCurrando) + "(" + String.valueOf(min) + "/" + String.valueOf(max) + ")", margenIzq + margenNombres + ((i-horaApertura)*sep)+sep/2, y+1, true);
			if (cabeTodo)
				gc.drawText(String.valueOf(personasCurrandoHorasCompletas) + "-" + String.valueOf(personasCurrando) , margenIzq + margenNombres + ((i-horaApertura)*sep)+sep/2 - posTexto, y+1, true);
			else
				gc.drawText(String.valueOf(personasCurrando) , margenIzq + margenNombres + ((i-horaApertura)*sep)+sep/2 - posTexto, y+1, true);
		}
	}
	
	/**
	 * Método que actualiza el estado comprobando si la vista ha cargado ya
	 * los datos de la cache o no.
	 * @return si se han cargado los datos de la cache
	 */
	public boolean actualizar() {
		return vista.isCacheCargada();
	}
	
	public void setColorTurno(Color color) {
		if (turno!=null)
			turno.setColor(color);
		redibujar();
	}
	
	/**
	 * Método que se encarga de guardar en la base de datos
	 * el cuadrante que se representa en la vista mes.
	 * @param primerDia		día por el que se va a empezar a modificar 
	 * 						el cuadrante de la base de datos
	 */
	public void cuadABD(int primerDia) {
		Cuadrante cuadABD=new Cuadrante(mes,anio,departamento);
		for (int i=primerDia-1;i<iCuad.length;i++) {
			for (int j=0;j<iCuad[i].size();j++) {
				cuadABD.getCuad()[i].add(new Trabaja(iCuad[i].get(j).getEmpl().getEmplId(),
						iCuad[i].get(j).getFichIni(),iCuad[i].get(j).getFichFin(),
						iCuad[i].get(j).getTurno().getIdTurno()));
			}
		}
		vista.modificarCuadrante(primerDia,mes,anio,departamento,cuadABD);
	}
	
	/**
	 * Se usa para crear un nuevo objeto Cuadrante que contendrá el cuadrante 
	 * representado en la vista mensual.
	 * @return
	 */
	public Cuadrante deICuadACuadrante() {
		Cuadrante cuadR = new Cuadrante(mes, anio, departamento);
		for (int i=0;i<iCuad.length;i++) {
			for (int j=0;j<iCuad[i].size();j++) {
				cuadR.getCuad()[i].add(new Trabaja(iCuad[i].get(j).getEmpl().getEmplId(),
						iCuad[i].get(j).getFichIni(),iCuad[i].get(j).getFichFin(),
						iCuad[i].get(j).getTurno().getIdTurno()));
			}
		}
		return cuadR;
	}
	
	/**
	 * Manda el cuadrante que se visualiza en la vista mes a la cache, para
	 * actualizar así los cambios que se hayan realizado en él.
	 */
	@SuppressWarnings("unchecked")
	public void cuadAcache() {
		Cuadrante cuadAcache=vista.getCuadrante(mes, anio, departamento);
		ArrayList<Trabaja> cuad[]=new ArrayList[iCuad.length];
		for (int i=0;i<iCuad.length;i++) {
			cuad[i]=new ArrayList<Trabaja>();
			for (int j=0;j<iCuad[i].size();j++) {
				cuad[i].add(new Trabaja(iCuad[i].get(j).getEmpl().getEmplId(),
						iCuad[i].get(j).getFichIni(),iCuad[i].get(j).getFichFin(),
						iCuad[i].get(j).getTurno().getIdTurno()));
			}
		}
		cuadAcache.setCuad(cuad);
	}
	
	/**
	 * Establece en la pantalla de la vista mes, el cuadrante que se le pasa por
	 * parámetro.
	 * @param c		Cuadrante a establecer
	 */
	@SuppressWarnings("unchecked")
	public void desReHacerICuad(Cuadrante c) {
		iCuad = new ArrayList[c.getCuad().length];
		for (int i=0; i<c.getCuad().length; i++) {					
			iCuad[i] = new ArrayList<I_Trabaja>();			
			for (int j=0; j<c.getCuad()[i].size(); j++) {
				iCuad[i].add(new I_Trabaja(c.getCuad()[i].get(j)));			
			}
		}
		cuadAcache();
		calcularTamano();
		canvas.redraw();
		//cuadModificado = false;
		//if (bGuardar!=null) bGuardar.setEnabled(false);
	}
	
	/**
	 * Método al que se llama desde la clase ShellPrincipal para poder deshacer
	 * o rehacer, los cuadrantes que se encuentran en las pilas del objeto de la
	 * clase CaretakerCuadrante, que representan el historial de modificaciones
	 * de la vista mensual.
	 * @param desReHacer	booleano para saber si se va a deshacer o a rehacer
	 */
	public void desReHacerICuadShellPrincipal(boolean desReHacer) {
		if (desReHacer) {
			if (!historialPilas.getPilaCuadsDeshacer().isEmpty()) {
				historialPilas.getPilaCuadsRehacer().push(deICuadACuadrante());
				if (bRehacer!=null) bRehacer.setEnabled(true);
				//if (!historialPilas.getPilaCuadsDeshacer().isEmpty()) {
				desReHacerICuad(historialPilas.getPilaCuadsDeshacer().pop());
					//if (historialPilas.getPilaCuadsDeshacer().isEmpty())
						//if (bDeshacer!=null) bDeshacer.setEnabled(false);	
				if (bGuardar!=null && !bGuardar.getEnabled())
					bGuardar.setEnabled(true);
				cuadModificado=true;
				if (!pilaRebosada && historialPilas.getPilaCuadsDeshacer().isEmpty())
					if (bDeshacer!=null) bDeshacer.setEnabled(false);
			}
			else {
				if (pilaRebosada) {
					MessageBox messageBox = new MessageBox(canvas.getShell(),
							SWT.APPLICATION_MODAL | SWT.YES | SWT.NO);
					messageBox.setText(bundle.getString("Aviso"));
					messageBox.setMessage(bundle.getString("I02_restaurar_cuadrante_inicial"));
					if (messageBox.open()==SWT.YES) {
						historialPilas.getPilaCuadsRehacer().push(deICuadACuadrante());
						if (bRehacer!=null) bRehacer.setEnabled(true);
						desReHacerICuad(cuadInicialDeshacer);
						if (bDeshacer!=null) bDeshacer.setEnabled(false);
						if (bGuardar!=null && !bGuardar.getEnabled())
							bGuardar.setEnabled(true);
						cuadModificado=true;
						primerCuadActivo=true;
					}
				}
			}
		}
		else
		{
			if (!primerCuadActivo)
				historialPilas.getPilaCuadsDeshacer().push(deICuadACuadrante());
			else
				primerCuadActivo=false;
			if (bDeshacer!=null) bDeshacer.setEnabled(true);
			if (!historialPilas.getPilaCuadsRehacer().isEmpty()) {
				desReHacerICuad(historialPilas.getPilaCuadsRehacer().pop());
				if (historialPilas.getPilaCuadsRehacer().isEmpty())
					if (bRehacer!=null) bRehacer.setEnabled(false);
			}
			else {
				//desReHacerICuad(cuadInicialDeshacer);
				if (bRehacer!=null	) bRehacer.setEnabled(false);
			}
			if (bGuardar!=null && !bGuardar.getEnabled())
				bGuardar.setEnabled(true);
			cuadModificado=true;
		}
	}
	
	/**
	 * Introduce el cuadrante que se encuentra en la pantalla actualmente, dentro 
	 * de la pila de deshacer cambios. Es llamado cuando se producen modificaciones,
	 * para ir guardando el historial de modificaciones. 
	 */
	public void pushCuadranteDeshacer () {
		if (historialPilas.getPilaCuadsDeshacer().size() > historialPilas.getMaxCuadsDeshacer()) {
			//Hay que probarlo, no se si es 0 o pilaCuadsDeshacer.size()-1
			if (!primerCuadActivo) {
				historialPilas.getPilaCuadsDeshacer().remove(0);
				historialPilas.getPilaCuadsDeshacer().push(deICuadACuadrante());
			}
			else
				primerCuadActivo=false;
			if (!historialPilas.getPilaCuadsRehacer().isEmpty()) {
				historialPilas.getPilaCuadsRehacer().removeAllElements();
			}
			pilaRebosada = true;
		}
		else {
			if (!historialPilas.getPilaCuadsRehacer().isEmpty()) {
				historialPilas.getPilaCuadsRehacer().removeAllElements();
			}
			if (!primerCuadActivo)
				historialPilas.getPilaCuadsDeshacer().push(deICuadACuadrante());
			else
				primerCuadActivo=false;
		}
		if (bRehacer!=null) bRehacer.setEnabled(false);
	}
	
}